﻿// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证（版本 2.0）进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动！任何基于本项目二次开发而产生的一切法律纠纷和责任，我们不承担任何责任！

using Admin.NET.Application.Entity;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WCS.Application.Entity.Warehous;
using WCS.Application.Service.Materialssuance;

namespace WCS.Application.Service.OrderDetaillssuance;
public class OrderDetaillssuanceService : IDynamicApiController, ITransient
{
    private readonly SqlSugarRepository<OrderDetailEntity> _orderDetailRep;
    private readonly UserManager _userinfo;


    public OrderDetaillssuanceService(UserManager userinfo, 
        SqlSugarRepository<OrderDetailEntity> orderDetail)
    {
        _orderDetailRep = orderDetail;
        _userinfo = userinfo;
    }

    /// <summary>
    /// 获取领料下发信息 🔖
    /// </summary>
    /// <param name="orderDetail"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "GetOrderDetailPageList"), HttpPost]
    public async Task<SqlSugarPagedList<OrderDetailEntity>> GetOrderDetailPageList(OrderDetailCreateDto orderDetail)
    {
        // status用枚举判断了
        var list = await _orderDetailRep.AsQueryable()
                .WhereIF(!string.IsNullOrWhiteSpace(orderDetail.PickingNumber), u => u.PickingNumber.Contains(orderDetail.PickingNumber.Trim()))
                .WhereIF(!string.IsNullOrWhiteSpace(orderDetail.Tray), u => u.Tray.Contains(orderDetail.Tray.Trim()))
                .OrderBuilder(orderDetail)
                .ToPagedListAsync(orderDetail.Page, orderDetail.PageSize);
        return list;
    }

    /// <summary>
    /// 获取领料下发信息 🔖
    /// </summary>
    /// <param name="orderDetail"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "GetOrderDetailList"), HttpPost]
    public async Task<List<OrderDetailEntity>> GetOrderDetailList(OrderDetailQueryDto orderDetail)
    {
        Expression<Func<OrderDetailEntity, bool>> expression = whereExp =>
                 (orderDetail.PickingNumber.GetIsEmptyOrNull() || whereExp.PickingNumber.Contains((orderDetail.PickingNumber.Trim())))
                 && (orderDetail.Tray.GetIsEmptyOrNull() || whereExp.Tray.Equals(orderDetail.Tray))
                 && (orderDetail.EntranceandExit.GetIsEmptyOrNull() || whereExp.EntranceandExit.Equals(orderDetail.EntranceandExit));

        var list = await _orderDetailRep.AsQueryable().WhereIF(expression != null, expression).OrderBuilder(orderDetail).ToListAsync();
        return list;
    }

    /// <summary>
    /// 添加领料下发
    /// </summary>
    /// <param name="Input"></param>
    /// <returns></returns>

    [ApiDescriptionSettings(Name = "InsertOrderDetail"), HttpPost]

    public async Task<long> InsertOrderDetail(OrderDetailCreateDto Input)
    {
        #region 唯一索引
        Expression<Func<OrderDetailEntity, bool>> whereExpression = whereExp =>
                    whereExp.PickingNumber.Equals(Input.PickingNumber)
                   && whereExp.Tray.Equals(Input.Tray)
                   ;
        #endregion
        var data = await _orderDetailRep.GetFirstAsync(whereExpression);
        if (data != null)
        {
            throw Oops.Oh(10001, "该记录已存在");
        }
        if (Input.PickingNumber == null)
        {
            Input.PickingNumber = await GenerateOrderIdAsync();
        }

        var entity = Input.Adapt<OrderDetailEntity>();

        await _orderDetailRep.AsInsertable(entity).ExecuteCommandAsync();
        return entity.Id;
    }

    /// <summary>
    /// 修改领料下发
    /// </summary>
    /// <param name="entity"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "UpdateOrderDetail"), HttpPost]

    public async Task<int> UpdateOrderDetail(OrderDetailUpdateDto entity)
    {
        SerilogHelper.WriteLog("OrderDetailService", "修改领料下发开始", JsonConvert.SerializeObject(entity));
        #region 唯一索引
        Expression<Func<OrderDetailEntity, bool>> whereExpression = whereExp =>
                    whereExp.Id.Equals(entity.Id);
        #endregion
        var OrderDetail = await _orderDetailRep.GetFirstAsync(u => u.Id == entity.Id);

        try
        {
            if (OrderDetail != null)
            {


                //对实体进行赋值
                entity.UpdateUserId = _userinfo.UserId;
                entity.UpdateTime = DateTime.Now;
                entity.UpdateUserName = _userinfo.RealName;
            }
            else
            {

                throw Oops.Oh(ErrorCodeEnum.D1002);
            }
        }
        catch (Exception error)
        {
            throw Oops.Oh("修改领料出现错误：" + error.Message + "");
        }
        //api已转为entity
        // 将 DTO 转换为实体
        var dataentity = entity.Adapt<OrderDetailEntity>();

       return await _orderDetailRep.AsUpdateable(dataentity).ExecuteCommandAsync();

    }
    /// <summary>
    /// 批量删除
    /// </summary>
    /// <param name="inputList"></param>
    /// <returns></returns>
    [UnitOfWork]
    [ApiDescriptionSettings(Name = "BatchDeleteOrderDetail"), HttpDelete]
    [DisplayName("批量删除")]
    public virtual async Task<int> BatchDeleteOrderDetail(List<OrderDetailDeleteDto> inputList)
    {
        #region "校验"
        foreach (var input in inputList)
        {
            Expression<Func<OrderDetailEntity, bool>> whereExpression = whereExp =>
                        whereExp.Id.Equals(input.Id)
                   ;
            var data = await _orderDetailRep.GetFirstAsync(whereExpression);
            if (data == null)
            {
                throw Oops.Oh("该记录不存在");
            }

            // *****校验是否有其他表使用该记录*****
        }
        #endregion

        var deleteEntity = inputList.Adapt<List<OrderDetailEntity>>();
        return await _orderDetailRep.AsDeleteable()
            .Where(deleteEntity)
            .ExecuteCommandAsync();
    }
    /// <summary>
    /// 下载模版
    /// </summary>
    /// <returns></returns>
    [UnitOfWork]
    [DisplayName("下载模版")]
    [HttpGet]
    public virtual async Task<IActionResult> DownloadOrderDetail()
    {
        return await Task.Run(() =>
        {
            #region "校验"
            string fileName = "OrderDetail.xlsx";
            string filePath = $"{AppDomain.CurrentDomain.BaseDirectory}/Template/{fileName}";
            if (!File.Exists(filePath))
            {
                throw Oops.Oh(10002, "找不到该模板：" + filePath);
            }
            #endregion

            var path = Path.Combine(filePath);
            return new FileStreamResult(new FileStream(path, FileMode.Open), System.Net.Mime.MediaTypeNames.Application.Octet)
            {
                FileDownloadName = fileName
            };
        });
    }
    /// <summary>  
    /// 生成订单号（当前时间+流水号）  
    /// </summary>  
    /// <returns></returns>  
    public async Task<string> GenerateOrderIdAsync()
    {
        var currentDate = "MOVE" + DateTime.Now.ToString("yyyyMMddHHmmss");
        var maxOrderId = await _orderDetailRep.AsQueryable()
            .Where(o => o.PickingNumber.StartsWith(currentDate))
            .MaxAsync(o => o.PickingNumber);

        var sequenceNumber = 1;
        if (!string.IsNullOrEmpty(maxOrderId))
        {
            var numberPart = maxOrderId.Substring(currentDate.Length);
            if (int.TryParse(numberPart, out int numericValue))
            {
                sequenceNumber = numericValue + 1;
            }
        }

        return $"{currentDate}{sequenceNumber.ToString().PadLeft(4, '0')}";
    }
    /// <summary>
    /// 导出设备信息为 Excel
    /// </summary>
    [UnitOfWork]
    [DisplayName("导出设备为Excel")]
    [ApiDescriptionSettings(Name = "OrderDetailExportExcel"), HttpPost]
    public virtual async Task<IActionResult> OrderDetailExportExcel([FromBody] OrderDetailQueryDto input)
    {
        var list = await GetOrderDetailList(input); 

        // 使用 NPOI 创建 Excel 文件
        var workbook = new NPOI.XSSF.UserModel.XSSFWorkbook();
        var sheet = workbook.CreateSheet("领料下发");

        // 创建表头
        var headerRow = sheet.CreateRow(0);
        headerRow.CreateCell(0).SetCellValue("序号");
        headerRow.CreateCell(1).SetCellValue("领料单号");
        headerRow.CreateCell(2).SetCellValue("托盘");
        headerRow.CreateCell(3).SetCellValue("出入口");


        // 填充数据
        for (int i = 0; i < list.Count; i++)
        {
            var row = sheet.CreateRow(i + 1);
            var device = list[i];
            row.CreateCell(0).SetCellValue(device.SerialNumber);
            row.CreateCell(1).SetCellValue(device.PickingNumber);
            row.CreateCell(2).SetCellValue(device.Tray);
            row.CreateCell(3).SetCellValue(device.EntranceandExit.ToString());
        }

        // 将 Excel 文件写入内存流
        using var memoryStream = new MemoryStream();
        workbook.Write(memoryStream);
        var bytes = memoryStream.ToArray();

        // 返回文件结果
        return new FileContentResult(bytes, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
        {
            FileDownloadName = "OrderDetailExport.xlsx"
        };
    }

    /// <summary>
    /// 导领料下发
    /// </summary>
    /// <param name="file"></param>
    /// <returns></returns>

    [UnitOfWork]
    [DisplayName("导入领料下发")]
    [ApiDescriptionSettings(Name = "ImportOrderDetail"), HttpPost]
    public virtual async Task<List<ImportOrderDetailOutput>> ImportOrderDetail([Required] IFormFile file)
    {

        if (file != null)
        {
            var fileDir = AppDomain.CurrentDomain.BaseDirectory + @"ImportFile";
            if (!Directory.Exists(fileDir))

            {
                Directory.CreateDirectory(fileDir);
            }
            //文件名称
            string fileName = file.FileName;
            //文件类型
            string fileType = file.FileName.Substring(fileName.LastIndexOf("."));
            //上传的文件的路径
            string filePath = fileDir + $@"/{fileName}";
            if (File.Exists(filePath))
            {
                File.Delete(filePath);
            }
            using (FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite))
            {
                file.CopyTo(fs);
            }

            if (fileType == ".xlsx" || fileType == ".xls")
            {
                ExcelHelper eh = new ExcelHelper(filePath);
                DataTable dt = eh.ExcelToDataTable("", true);
                eh.Dispose();
                if (dt == null || dt.Rows.Count == 0)
                {
                    throw Oops.Oh("文件为空！");
                }

                #region "校验模板字段"
                if (!dt.Columns.Contains("序号") || !dt.Columns.Contains("单号") || !dt.Columns.Contains("库位码") || !dt.Columns.Contains("出库口"))
                {
                    throw Oops.Oh("文件模板错误！请重新下载模板");
                }
                var orderid = string.Empty;

                //不存在订单编号自己生成
                 orderid = await GenerateOrderIdAsync();

                #endregion

                List<ImportOrderDetailOutput> listLoad = new List<ImportOrderDetailOutput>();
                int i = 0;
                foreach (DataRow row in dt.Rows)
                {
                    i++;
                    //校验关联信息
                    ImportOrderDetailOutput orderDetailIssuance = new ImportOrderDetailOutput
                    {
                        SerialNumber = row["序号"].GetCString(),
                        PickingNumber = row["单号"].GetCString(),
                        Tray = row["库位码"].GetCString(),
                        EntranceandExit = row["出库口"].GetCString(),

                    };
                    #region "校验必填项"

                    #endregion
                    //用唯一索引查询非重复
                    Expression<Func<OrderDetailEntity, bool>> whereExpression = whereExp =>
                        whereExp.PickingNumber.Equals(orderDetailIssuance.PickingNumber)
                        && whereExp.Tray.Equals(orderDetailIssuance.Tray)
                        ;
                    var data = await _orderDetailRep.GetFirstAsync(whereExpression);
                    if (data == null)
                    {
                        #region "自定义校验"

                        data = _orderDetailRep.Adapt(orderDetailIssuance);
                        #endregion

                        var rtAdd = await _orderDetailRep.AsInsertable(data).ExecuteCommandAsync();
                        if (rtAdd != 1)
                        {
                            orderDetailIssuance.ResultCode = 10004;
                            orderDetailIssuance.Message = "插入失败";
                        }
                    }
                    else
                    {
                        #region "自定义校验"  

                        data.UpdateUserId = _userinfo.UserId;
                        data.UpdateTime = DateTime.Now;
                        data.UpdateUserName = _userinfo.RealName;
                        data.SerialNumber  = orderDetailIssuance.SerialNumber;
                        data.PickingNumber = orderDetailIssuance.PickingNumber;
                        data.EntranceandExit = orderDetailIssuance.EntranceandExit;
                        data.Tray = orderDetailIssuance.Tray;

                        // 使用 Mapster 的 Adapt 方法将 orderInfoEntity 的值替换到 data 中  

                        //不能用Adapt替换因为importPosition中没主键

                        var order = data.Adapt(orderDetailIssuance);
                        var rtUpdate = await _orderDetailRep.AsUpdateable(order).ExecuteCommandAsync();
                        if (rtUpdate != 1)
                        {
                            orderDetailIssuance.ResultCode = 10004;
                            orderDetailIssuance.Message = "更新失败";
                        }
                    }

                    if (orderDetailIssuance.ResultCode != 200)
                        listLoad.Add(orderDetailIssuance);
                }

                // 返回导入失败数据
                if (listLoad.Count > 0)
                {
                    return listLoad;
                }
            }
            else
            {
                throw Oops.Oh(10002, "文件内容为空！");
            }
        }
        else
        {
            throw Oops.Oh(10002, "请选择文件！");
        }
        return null;
    }
    #endregion
}
